// 引入SqlSugar ORM相关命名空间
using SqlSugar;
// 引入项目中的实体模型
using Rabbit3.Api.Models;
// 引入项目中的数据传输对象
using Rabbit3.Api.Dto;
// 引入AutoMapper对象映射相关命名空间
using AutoMapper;

namespace Rabbit3.Api.Services
{
    /// <summary>
    /// 溯源信息服务接口 - 定义溯源信息相关的业务操作
    /// 提供溯源信息的增删改查、完整度计算、溯源码导出等功能
    /// </summary>
    public interface ITraceabilityService
    {
        /// <summary>
        /// 分页查询溯源信息 - 支持按条件筛选和分页显示
        /// </summary>
        /// <param name="queryDto">查询条件DTO，包含分页参数和筛选条件</param>
        /// <returns>分页结果，包含数据列表和分页信息</returns>
        Task<PagedResponseDto<TraceabilityResponseDto>> GetPagedListAsync(QueryTraceabilityDto queryDto);

        /// <summary>
        /// 根据ID获取单个溯源信息详情
        /// </summary>
        /// <param name="id">溯源信息ID</param>
        /// <returns>溯源信息详情，如果不存在返回null</returns>
        Task<TraceabilityResponseDto?> GetByIdAsync(int id);

        /// <summary>
        /// 创建新的溯源信息
        /// </summary>
        /// <param name="createDto">创建溯源信息的DTO对象</param>
        /// <returns>创建成功后的溯源信息详情</returns>
        Task<TraceabilityResponseDto> CreateAsync(CreateTraceabilityDto createDto);

        /// <summary>
        /// 更新现有的溯源信息
        /// </summary>
        /// <param name="updateDto">包含更新数据的DTO对象</param>
        /// <returns>更新后的溯源信息详情，如果不存在返回null</returns>
        Task<TraceabilityResponseDto?> UpdateAsync(UpdateTraceabilityDto updateDto);

        /// <summary>
        /// 软删除指定的溯源信息（逻辑删除，不物理删除）
        /// </summary>
        /// <param name="id">要删除的溯源信息ID</param>
        /// <returns>删除是否成功</returns>
        Task<bool> DeleteAsync(int id);

        /// <summary>
        /// 批量软删除多个溯源信息（逻辑删除，不物理删除）
        /// </summary>
        /// <param name="ids">要删除的溯源信息ID列表</param>
        /// <returns>批量删除是否成功</returns>
        Task<bool> BatchDeleteAsync(List<int> ids);

        /// <summary>
        /// 导出指定溯源信息的溯源码（用于生成二维码或条形码）
        /// </summary>
        /// <param name="id">溯源信息ID</param>
        /// <returns>溯源码字符串，如果不存在返回null</returns>
        Task<string?> ExportTraceabilityCodeAsync(int id);

        /// <summary>
        /// 计算指定溯源信息的完整度百分比
        /// 完整度基于各个阶段信息的完整性：养殖、屠宰、深加工、企业信息、供应商信息
        /// </summary>
        /// <param name="traceabilityId">溯源信息ID</param>
        /// <returns>完整度百分比（0-100）</returns>
        Task<int> CalculateCompletenessAsync(int traceabilityId);
    }

    /// <summary>
    /// 溯源信息服务实现类 - 实现溯源信息相关的业务逻辑
    /// 负责处理溯源信息的增删改查、完整度计算、溯源码导出等操作
    /// </summary>
    public class TraceabilityService : ITraceabilityService
    {
        // SqlSugar数据库客户端，用于执行数据库操作
        private readonly ISqlSugarClient _db;
        // AutoMapper映射器，用于对象之间的映射转换
        private readonly IMapper _mapper;

        /// <summary>
        /// 构造函数 - 通过依赖注入初始化服务
        /// </summary>
        /// <param name="db">SqlSugar数据库客户端实例</param>
        /// <param name="mapper">AutoMapper映射器实例</param>
        public TraceabilityService(ISqlSugarClient db, IMapper mapper)
        {
            // 初始化数据库客户端
            _db = db;
            // 初始化映射器
            _mapper = mapper;
        }

        /// <summary>
        /// 分页查询溯源信息
        /// </summary>
        /// <param name="queryDto">查询条件</param>
        /// <returns>分页结果</returns>
        public async Task<PagedResponseDto<TraceabilityResponseDto>> GetPagedListAsync(QueryTraceabilityDto queryDto)
        {
            var query = _db.Queryable<TraceabilityInfo>()
                .Where(x => !x.IsDeleted);

            // 添加搜索条件
            if (!string.IsNullOrEmpty(queryDto.ProductName))
            {
                query = query.Where(x => x.ProductName.Contains(queryDto.ProductName));
            }

            if (!string.IsNullOrEmpty(queryDto.ProductionBatch))
            {
                query = query.Where(x => x.ProductionBatch.Contains(queryDto.ProductionBatch));
            }

            if (!string.IsNullOrEmpty(queryDto.ProductionEnterprise))
            {
                query = query.Where(x => x.ProductionEnterprise.Contains(queryDto.ProductionEnterprise));
            }

            if (!string.IsNullOrEmpty(queryDto.ProductionLicenseNumber))
            {
                query = query.Where(x => x.ProductionLicenseNumber.Contains(queryDto.ProductionLicenseNumber));
            }

            // 获取总数
            var totalCount = await query.CountAsync();

            // 分页查询
            var list = await query
                .OrderByDescending(x => x.CreatedAt)
                .Skip((queryDto.PageIndex - 1) * queryDto.PageSize)
                .Take(queryDto.PageSize)
                .ToListAsync();

            // 映射为DTO
            var responseList = _mapper.Map<List<TraceabilityResponseDto>>(list);

            return new PagedResponseDto<TraceabilityResponseDto>
            {
                Data = responseList,
                TotalCount = totalCount,
                TotalPages = (int)Math.Ceiling((double)totalCount / queryDto.PageSize),
                PageIndex = queryDto.PageIndex,
                PageSize = queryDto.PageSize
            };
        }

        /// <summary>
        /// 根据ID获取溯源信息
        /// </summary>
        /// <param name="id">ID</param>
        /// <returns>溯源信息</returns>
        public async Task<TraceabilityResponseDto?> GetByIdAsync(int id)
        {
            var entity = await _db.Queryable<TraceabilityInfo>()
                .Where(x => x.Id == id && !x.IsDeleted)
                .FirstAsync();

            return entity == null ? null : _mapper.Map<TraceabilityResponseDto>(entity);
        }

        /// <summary>
        /// 创建溯源信息
        /// </summary>
        /// <param name="createDto">创建DTO</param>
        /// <returns>创建结果</returns>
        public async Task<TraceabilityResponseDto> CreateAsync(CreateTraceabilityDto createDto)
        {
            var entity = _mapper.Map<TraceabilityInfo>(createDto);
            
            var id = await _db.Insertable(entity).ExecuteReturnIdentityAsync();
            entity.Id = id;

            return _mapper.Map<TraceabilityResponseDto>(entity);
        }

        /// <summary>
        /// 更新溯源信息
        /// </summary>
        /// <param name="updateDto">更新DTO</param>
        /// <returns>更新结果</returns>
        public async Task<TraceabilityResponseDto?> UpdateAsync(UpdateTraceabilityDto updateDto)
        {
            var entity = await _db.Queryable<TraceabilityInfo>()
                .Where(x => x.Id == updateDto.Id && !x.IsDeleted)
                .FirstAsync();

            if (entity == null)
                return null;

            _mapper.Map(updateDto, entity);
            
            await _db.Updateable(entity).ExecuteCommandAsync();

            return _mapper.Map<TraceabilityResponseDto>(entity);
        }

        /// <summary>
        /// 删除溯源信息
        /// </summary>
        /// <param name="id">ID</param>
        /// <returns>删除结果</returns>
        public async Task<bool> DeleteAsync(int id)
        {
            var result = await _db.Updateable<TraceabilityInfo>()
                .SetColumns(x => new TraceabilityInfo { IsDeleted = true, UpdatedAt = DateTime.Now })
                .Where(x => x.Id == id && !x.IsDeleted)
                .ExecuteCommandAsync();

            return result > 0;
        }

        /// <summary>
        /// 批量删除溯源信息
        /// </summary>
        /// <param name="ids">ID列表</param>
        /// <returns>删除结果</returns>
        public async Task<bool> BatchDeleteAsync(List<int> ids)
        {
            var result = await _db.Updateable<TraceabilityInfo>()
                .SetColumns(x => new TraceabilityInfo { IsDeleted = true, UpdatedAt = DateTime.Now })
                .Where(x => ids.Contains(x.Id) && !x.IsDeleted)
                .ExecuteCommandAsync();

            return result > 0;
        }

        /// <summary>
        /// 导出溯源码
        /// </summary>
        /// <param name="id">ID</param>
        /// <returns>溯源码</returns>
        public async Task<string?> ExportTraceabilityCodeAsync(int id)
        {
            var entity = await _db.Queryable<TraceabilityInfo>()
                .Where(x => x.Id == id && !x.IsDeleted)
                .FirstAsync();

            return entity?.TraceabilityCode;
        }

        /// <summary>
        /// 计算溯源信息完整度
        /// </summary>
        /// <param name="traceabilityId">溯源信息ID</param>
        /// <returns>完整度百分比</returns>
        public async Task<int> CalculateCompletenessAsync(int traceabilityId)
        {
            int totalSteps = 5; // 总步骤数：养殖、屠宰、深加工、企业信息、供应商信息
            int completedSteps = 0;

            // 检查养殖信息
            var farmingInfo = await _db.Queryable<FarmingInfo>()
                .Where(x => x.TraceabilityId == traceabilityId && !x.IsDeleted)
                .FirstAsync();
            if (farmingInfo != null)
            {
                completedSteps++;
            }

            // 检查屠宰信息
            var slaughterInfo = await _db.Queryable<SlaughterInfo>()
                .Where(x => x.TraceabilityId == traceabilityId && !x.IsDeleted)
                .FirstAsync();
            if (slaughterInfo != null)
            {
                completedSteps++;
            }

            // 检查深加工信息
            var processingInfo = await _db.Queryable<ProcessingInfo>()
                .Where(x => x.TraceabilityId == traceabilityId && !x.IsDeleted)
                .FirstAsync();
            if (processingInfo != null)
            {
                completedSteps++;
            }

            // 检查企业信息（至少有一个阶段的企业信息）
            var enterpriseCount = await _db.Queryable<EnterpriseInfo>()
                .Where(x => x.TraceabilityId == traceabilityId && !x.IsDeleted)
                .CountAsync();
            if (enterpriseCount > 0)
            {
                completedSteps++;
            }

            // 检查供应商信息
            var supplierCount = await _db.Queryable<SupplierInfo>()
                .Where(x => x.TraceabilityId == traceabilityId && !x.IsDeleted)
                .CountAsync();
            if (supplierCount > 0)
            {
                completedSteps++;
            }

            // 计算完整度百分比
            int completeness = (int)Math.Round((double)completedSteps / totalSteps * 100);

            // 更新溯源信息的完整度
            await _db.Updateable<TraceabilityInfo>()
                .SetColumns(x => new TraceabilityInfo { InformationCompleteness = completeness, UpdatedAt = DateTime.Now })
                .Where(x => x.Id == traceabilityId && !x.IsDeleted)
                .ExecuteCommandAsync();

            return completeness;
        }
    }
}
